package cn.turboinfo.fuyang.api.domain.mini.usecase.login;

import cn.turboinfo.fuyang.api.domain.common.service.user.SysUserService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserLoginService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserThirdPartyService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserTypeRelService;
import cn.turboinfo.fuyang.api.domain.common.service.wechat.WechatService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.domain.mini.service.session.MiniSessionService;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.LoginCheckType;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.LoginNameType;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.ThirdPartyType;
import cn.turboinfo.fuyang.api.entity.common.fo.wechat.WechatAuthResult;
import cn.turboinfo.fuyang.api.entity.common.fo.wechat.WechatGetPhoneResult;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUser;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUserCreator;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserLogin;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserThirdPartyCreator;
import cn.turboinfo.fuyang.api.entity.mini.pojo.session.MiniSession;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.base.enums.EnableStatus;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * 微信登录
 *
 * @author hai
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniLoginByWechatUseCase extends AbstractUseCase<MiniLoginByWechatUseCase.InputData, MiniLoginByWechatUseCase.OutputData> {

    private final MiniSessionService miniSessionService;

    private final WechatService wechatService;

    private final UserThirdPartyService userThirdPartyService;

    private final UserLoginService userLoginService;

    private final SysUserService sysUserService;

    private final UserTypeRelService userTypeRelService;

    @Override
    protected OutputData doAction(InputData inputData) {
        String openid;
        String phoneCode = inputData.getPhoneCode();
        Long userId;
        try {
            WechatAuthResult result = wechatService.auth(inputData.getAuthCode());
            openid = result.getOpenid();

        } catch (Exception e) {
            log.error("微信授权失败: {}", e.getMessage());
            throw new RuntimeException("授权失败：请重新授权");

        }
        // 从登录方式检查用户是否存在
        List<UserLogin> loginList = userLoginService.findByLoginNameAndLoginNameType(openid, LoginNameType.THIRD_PARTY);

        if (loginList.isEmpty()) {

            String phoneNum;

            // 获取微信手机号
            try {
                WechatGetPhoneResult res = wechatService.getPhone(phoneCode);

                if (!"0".equals(res.getErrcode()) || res.getPhone_info() == null) {
                    throw new RuntimeException("获取手机号失败");
                }

                phoneNum = res.getPhone_info().getPurePhoneNumber();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            // 查询手机号是否存在
            loginList = userLoginService.findByLoginNameAndLoginNameType(phoneNum, LoginNameType.PHONE_NUM);

            if (loginList.isEmpty()) {
                log.error("用户不存在, 自动创建，openid: {}, mobile: {}", openid, phoneNum);
                // 创建用户
                SysUserCreator.Builder builder = SysUserCreator.builder()
                        .withMobile(phoneNum)
                        .withUsername(phoneNum)
                        .withStatus(EnableStatus.ENABLED);
                SysUser sysUser = sysUserService.save(builder.build(), null);

                //创建关联
                userTypeRelService.createConsumerRel(sysUser.getId());

                userId = sysUser.getId();

            } else {
                userId = loginList.get(0).getUserId();
            }
            log.error("绑定微信登录, openid: {} ", openid);

            UserThirdPartyCreator thirdPartyCreator = UserThirdPartyCreator
                    .builder()
                    .withUserId(userId)
                    .withThirdPartyAccount(openid)
                    .withThirdPartyType(ThirdPartyType.MINI_WECHAT)
                    .build();

            // 绑定微信三方账号
            userThirdPartyService.bindThirdPartyWithLogin(thirdPartyCreator, LoginCheckType.FRONT_THIRD_PARTY);

        } else {
            // 如果有则直接返回
            userId = loginList.get(0).getUserId();
        }

        // 登录成功后创建 Session
        MiniSession session = MiniSession
                .builder()
                .userId(userId)
                .build();

        String token = UUID.randomUUID().toString();
        miniSessionService.save(token, session);

        return OutputData.builder()
                .token(token)
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        @NotEmpty(message = "微信授权凭证")
        private String authCode;

        @NotEmpty(message = "手机号授权凭证")
        private String phoneCode;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 登录成功的会话令牌
         */
        private String token;

    }
}
